package service

import (
	"context"
	"encoding/json"
	"wxpay/internal/dao"
	"wxpay/internal/model"
	"wxpay/pkg/merrors"
)

type messageService struct {
	d dao.DataStore
}

func NewMessageService(d dao.DataStore) *messageService {
	return &messageService{d: d}
}

// 发送消息
func (s *messageService) Emit(ctx context.Context, msgId int64) (err error) {
	const op merrors.Op = "service.Emit"
	if msgId == 0 {
		// 无消息需要发送，直接返回
		return nil
	}
	msg, err := s.d.EventMessage().GetMessageById(ctx, msgId)
	if err != nil {
		return merrors.E(op, merrors.Invalid, err)
	}
	if !msg.IsMessageCreatedStatus() || msg.ReachMaxRetryCount() || !msg.IsTimeYet() {
		//	消息不是待发送状态不需要发送, 到达最多重试次数不需要发送, 未到发送时间不需要发送
		return nil
	}
	// 更新状态到发送中
	if err = s.d.EventMessage().UpdateMessageStatus(ctx, msgId, model.MessageCreatedStatus, model.MessagePublishingStatus); err != nil {
		return merrors.E(op, merrors.Invalid, err)
	}
	// 发送消息
	if err := s.d.EventMessage().PublishMessage(ctx, msg); err != nil {
		if msg.ReachMaxRetryCount() {
			// 更新状态到发送失败
			_ = s.d.EventMessage().UpdateMessageStatus(ctx, msgId, model.MessagePublishingStatus, model.MessageFailedStatus)
		} else {
			// 更新状态到待发送
			_ = s.d.EventMessage().UpdateMessageStatus(ctx, msgId, model.MessagePublishingStatus, model.MessageCreatedStatus)
		}
		return merrors.E(op, merrors.Invalid, err)

	}
	// 更新状态到发送成功
	if err = s.d.EventMessage().UpdateMessageStatus(ctx, msgId, model.MessagePublishingStatus, model.MessagePublishedStatus); err != nil {
		return merrors.E(op, merrors.Invalid, err)
	}
	return nil
}

// 加载待发送消息并发送
func (s *messageService) ScanThenInQueue(ctx context.Context) (err error) {
	msgs, err := s.d.EventMessage().GetMessagesAwaitPublish(ctx, model.Pagination{PageNo: 1, PageSize: 20})
	if err != nil {
		return err
	}
	var body [][]byte
	for _, msg := range msgs {
		s, _ := json.Marshal(&model.RetryMessage{ID: msg.ID})
		body = append(body, s)
	}
	if len(body) == 0 {
		return nil
	}
	return s.d.EventMessage().MultiPublishMessage(ctx, model.TopicMessageRetry, body)
}
